package com.example.opengl.player.extractor

import android.media.MediaExtractor
import android.media.MediaFormat
import java.nio.ByteBuffer

class MMExtractor(path: String) {
    /**音视频分离器**/
    private var mExtractor: MediaExtractor? = null

    /**音视轨道索引**/
    private var mAudioTrack = -1

    /**视视轨道索引**/
    private var mVideoTrack = -1

    /**当前帧时间戳**/
    private var mCurrentSampleTime: Long = 0

    /**当前帧标志**/
    private var mCurrentSampleFlag: Int = 0

    /**开始解码时间点**/
    private var mStartPos: Long = 0

    init {
        mExtractor = MediaExtractor()
        mExtractor?.setDataSource(path)
    }

    /**
     * 获取视频格式参数
     */
    fun getVideoFormat(): MediaFormat? {
        for (i in 0 until mExtractor!!.trackCount) {
            val mediaFormat = mExtractor!!.getTrackFormat(i)
            val mine = mediaFormat.getString(MediaFormat.KEY_MIME)
            if (mine?.startsWith("video/") == true) {
                mVideoTrack = i
                break
            }
        }
        return if (mVideoTrack >= 0) mExtractor!!.getTrackFormat(mVideoTrack) else null
    }

    /**
     * 获取音频格式参数
     */
    fun getAudioFormat(): MediaFormat? {
        for (i in 0 until mExtractor!!.trackCount) {
            val mediaFormat = mExtractor!!.getTrackFormat(i)
            val mine = mediaFormat.getString(MediaFormat.KEY_MIME)
            if (mine?.startsWith("audio/") == true) {
                mAudioTrack = i
                break
            }
        }
        return if (mAudioTrack >= 0) mExtractor!!.getTrackFormat(mAudioTrack) else null
    }

    /**
     * 读取视频数据
     */
    fun readBuffer(byteBuffer: ByteBuffer): Int {
        byteBuffer.clear()
        selectSourceTrack()
        val readSampleCount = mExtractor!!.readSampleData(byteBuffer, 0)
        //返回读取到的音视频数据流的大小，小于0表示数据已经读完
        if (readSampleCount < 0) return -1

        //记录当前帧时间戳
        mCurrentSampleFlag = mExtractor!!.sampleFlags
        mCurrentSampleTime = mExtractor!!.sampleTime
        //解码下一帧
        mExtractor!!.advance()
        return readSampleCount

    }

    /**
     * 选择通道
     */
    private fun selectSourceTrack() {
        if (mVideoTrack >= 0) {
            mExtractor!!.selectTrack(mVideoTrack)
        } else if (mAudioTrack >= 0) {
            mExtractor!!.selectTrack(mAudioTrack)
        }
    }
    /**
     * SeekTo到指定位置，并返回实际帧的时间戳
     * 指定的播放位置有一定误差，因此需要指定seek靠近哪个关键帧，有以下三种类型：
      SEEK_TO_PREVIOUS_SYNC：跳播位置的上一个关键帧
      SEEK_TO_NEXT_SYNC：跳播位置的下一个关键帧
      SEEK_TO_CLOSEST_SYNC：距离跳播位置的最近的关键帧
     */
    fun seek(pos:Long):Long{
        mExtractor!!.seekTo(pos,MediaExtractor.SEEK_TO_PREVIOUS_SYNC)

        return mExtractor!!.sampleTime
    }
    /**
     * 停止读取数据
     */
    fun stop(){
        mExtractor?.release()
        mExtractor = null
    }

    fun getAudioTrack():Int{
        return mAudioTrack
    }
    fun getVideoTrack():Int{
        return mVideoTrack
    }
    fun setStartPos(pos: Long){
        mStartPos = pos
    }

    /**
     * 获取当前帧时间
     */
    fun getCurrentTimestamp():Long{
        return mCurrentSampleTime
    }

    /**
     * 获取当前帧标记
     */
    fun getCurrentTimeFlag():Int{
        return mCurrentSampleFlag
    }


}